
package com.joysuch.wwyt.core.common.util;

import com.google.gson.Gson;
import com.joysuch.wwyt.monitoringcenter.bean.CameraMonitoringBean;
import javafx.util.Pair;
import lombok.Data;
import org.springframework.data.geo.Point;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;

public class MapUtils {

    private static final ThreadLocal<Pattern> coordsPatterns = new ThreadLocal<>();

    /**
     * 将坐标字符串解析为坐标点。坐标字符串必须符合如下格式: x:\\d+(\\.\\d+)?,y:\\d+(\\.\\d+)?
     * 例如: x:1234.890,y:208767.3232
     * 不符合规范，将返回null
     *
     * @param coordsString 坐标字符串
     * @return 坐标点。如果不符合规范，则返回null
     */
    public static Point parseCoordinate(String coordsString) {
        if (isCoordinates(coordsString)) {
            String[] split = coordsString.split(",");
            return new Point(Double.parseDouble(split[0].split(":")[1]), Double.parseDouble(split[1].split(":")[1]));
        }
        return null;
    }

    /**
     * 2019年12月16日21:07:16
     * <p>
     * 解析五位一体格式坐标
     * 不符合规范，将返回null
     *
     * @param coordsString 坐标字符串
     * @return 坐标点。如果不符合规范，则返回null
     */
    public static WwytPoint parseSinglePoint(String coordsString) {
        try {
            Gson gson = new Gson();
            WwytPoint point = gson.fromJson(coordsString, WwytPoint.class);
            return point;
        } catch (Exception e) {
        }
        return null;
    }

    /**
     * 将坐标字符串解析为坐标点集合。本处的坐标点集合必须满足 point1;point2;...规范
     * pointx规范，参考 {@link #parseCoordinate(String)}。如果不符合规范，将抛出IllegalArgumentException
     *
     * @param coordsString 坐标字符串
     * @return 坐标点。如果不符合规范，则返回null
     * @throws IllegalArgumentException 不符合规范的坐标点时
     */
    public static List<Point> parseCoordinates(String coordsString) throws IllegalArgumentException {
        String[] split = coordsString.split(";");
        List<Point> list = new ArrayList<Point>(split.length);
        for (String s : split) {
            Point point = parseCoordinate(s);
            if (point == null) {
                throw new IllegalArgumentException("不合法的字符串集合");
            }
            list.add(point);
        }
        return list;
    }

    private static Pattern getPattern() {
        Pattern pattern = coordsPatterns.get();
        if (pattern == null) {
            pattern = Pattern.compile("x:\\d+(\\.\\d+)?,y:\\d+(\\.\\d+)?(,floorId:\\d+)?");
            coordsPatterns.set(pattern);
        }
        return pattern;
    }

    private static boolean isCoordinates(String location) {
        if (location == null) {
            return false;
        }
        return getPattern().matcher(location).matches();
    }

    public static void resetCoordsPatterns() {
        coordsPatterns.remove();
    }

    public static List<Point> parsePointsFromJson(String jsonString) {
        ThreeDPoints points = parse3DPointsFromJson(jsonString);

        return points == null ? Collections.EMPTY_LIST : points.points;
    }

    public static ThreeDPoints parse3DPointsFromJson(String jsonString) {
        if (jsonString == null) {
            return null;
        }
        Gson gson = new Gson();
        try {
            ThreeDPoints points = gson.fromJson(jsonString, ThreeDPoints.class);
            return points;
        } catch (Exception e) {
        }
        return null;
    }

    public static SafetyPoints parse3DSafetyPointsFromJson(String jsonString) {
        if (jsonString == null) {
            return null;
        }
        Gson gson = new Gson();
        try {
            SafetyPoints points = gson.fromJson(jsonString, SafetyPoints.class);
            return points;
        } catch (Exception e) {
        }
        return null;
    }

    public static Point calculateCenterPoint(List<Point> points) {
        if (points == null || points.size() == 0) {
            return new Point(0, 0);
        }
        double x = 0;
        double y = 0;

        for (Point p : points) {
            x += p.getX();
            y += p.getY();
        }

        return new Point(x / points.size(), y / points.size());
    }
    
    public static SafetyPoint calculateCenterPointZ(List<SafetyPoint> points){
        if (points == null || points.size() == 0) {
            return new SafetyPoint();
        }
        double x = 0;
        double y = 0;
        double z = 0;
        for (SafetyPoint point : points) {
            x += point.getX();
            y += point.getY();
            z += point.getZ();
        }
        
        return new SafetyPoint(0L,(x / points.size()),y / points.size(),z / points.size());
    }

    public static Pair<Double, Double> calculateCameraCenter(List<CameraMonitoringBean> list) {
        if(list==null||list.size()==0){
            return new Pair<>(0d, 0d);
        }
        double x = 0;
        double y = 0;
        for (CameraMonitoringBean bean : list) {
            x += bean.getX();
            y += bean.getY();
        }
        return new Pair<>(x / list.size(), y / list.size());
    }

    @Data
    public static class ThreeDPoints {
        private Long floorId;
        private List<Point> points;
    }


    @Data
    public static class WwytPoint {
        private Long floorId;
        private Double x;
        private Double y;
        private Double z;

    }

    @Data
    public static class SafetyPoint {
        private Long floorId;
        private Double x;
        private Double y;
        private Double z;

        public SafetyPoint(long floorId, double x, double y, double z) {
            this.floorId = floorId;
            this.x = x;
            this.y = y;
            this.z = z;
        }

        public SafetyPoint() {
        }
    }

    @Data
    public static class SafetyPoints {
        private Long floorId;
        private List<SafetyPoint> points;
        private String buildingId;//000000
        //in室内 out室外
        private String inOrOutSide;
    }


    public static void getCoordinateArr(List<MapUtils.SafetyPoint> points, Double[] pointLons, Double[] pointLats) {
        int i = 0;
        for (MapUtils.SafetyPoint each : points) {
            pointLons[i] = each.getX();
            pointLats[i] = each.getY();
            i++;
        }
    }
}
